﻿using System.Web;

namespace BlogsAPI.Shorteners
{
    using System.Text.RegularExpressions;
    using System;
    using System.IO;
    using System.Net;
    using System.Text;
    using System.Xml;
    using Abstract;

    /// <summary>
    /// bit.ly is a utility that allows users to shorten a long URL, share it, and then track the resulting usage.
    /// </summary>
    /// <seealso cref="http://bit.ly/pages/help#i_0_0"/>
    [SingleShortener(Link = "http://bit.ly")]
    public class BitLy : Shortener
    {
        /// <summary>
        /// Конструктор по умолчанию
        /// </summary>
        public BitLy()
        {
            _username = "flashr";
            _apikey = "R_143ef25eb9ccae32fb5b54484a9f8be2";
        }

        /// <summary>
        /// Заполняем данными пользователя
        /// </summary>
        /// <param name="username">имя пользователя</param>
        /// <param name="key">ключ пользователя</param>
        public BitLy(String username,String key)
        {
            _username = username;
            _apikey = key;
        }

        /// <summary>
        /// Преобразование одного типа данных в другой
        /// </summary>
        /// <param name="sInData">входные данные</param>
        /// <param name="sInType">входной тип</param>
        /// <param name="sOutType">выходной тип</param>
        /// <returns>Данные выходного типа</returns>
        /// <remarks>The fuction has bad code style</remarks>
        public override String ConvertDataTo(string sInData, ItemType sInType, ItemType sOutType)
        {
            if(sInType == ItemType.Clicks) return null;//cant be!
            if(sOutType == ItemType.User) return null;//cant be!
            if (sInType == sOutType) return sInData;
            
            string itype;
            string btype;
            string xtype;

            if(sInType == ItemType.HashTag 
                && sOutType==ItemType.MetaTag)//Retrieves the metadata from a hash
            {
                btype = "info";
                xtype = "htmlMetaDescription";
                itype = "hash";
            }else if(sInType == ItemType.ShortUrl 
                && sOutType == ItemType.MetaTag) //Retrieves the metadata from a Short Url
            {
                btype = "info";
                xtype = "htmlMetaDescription";
                itype = "shortUrl";
            }else if(sInType == ItemType.HashTag
                && sOutType == ItemType.FullUrl) // Returns the Expanded url from a hash
            {
                btype = "expand";
                xtype = "longUrl";
                itype = "hash";
            }else if(sInType == ItemType.ShortUrl 
                && sOutType == ItemType.FullUrl)//Returns the Expanded url from a Short Url
            {
                btype = "expand";
                xtype = "longUrl";
                itype = "shortUrl";
            }else if(sInType == ItemType.FullUrl 
                && sOutType == ItemType.ShortUrl)
            //Shortens a long Url
            {
                btype = "shorten";
                xtype = "shortUrl";
                itype = "longUrl";
            }else if(sInType == ItemType.HashTag 
                && sOutType == ItemType.Clicks)
            //Returns number of clicks from a hash
            {
                btype = "stats";
                xtype = "clicks";
                itype = "hash";
            }else if(sInType == ItemType.ShortUrl
                && sOutType == ItemType.Clicks)
            //Returns number of clicks from a Short Url
            {
                btype = "stats";
                xtype = "clicks";
                itype = "shortUrl";
            }else if(sInType == ItemType.ShortUrl
                && sOutType == ItemType.User)
            //Returns user from a Short Url
            {
                btype = "info";
                xtype = "shortenedByUser";
                itype = "shortUrl";
            }else if(sInType == ItemType.HashTag
                && sOutType == ItemType.User)
            //Returns user from a Short Url
            {
                btype = "info";
                xtype = "shortenedByUser";
                itype = "hash";
            }else
            {
                return null;
            }

            StringBuilder url = new StringBuilder();  //Build a new string
            url.Append("http://api.bit.ly/");   //Add base URL
            url.Append(btype);
            url.Append("?version=2.0.1");             //Add Version
            url.Append("&format=xml");
            url.Append("&");
            url.Append(itype);
            url.Append("=");
            url.Append(HttpUtility.UrlEncode(sInData));                         //Append longUrl from input
            url.Append("&login=");                    //Add login "Key"
            url.Append(_username);                     //Append login from input
            url.Append("&apiKey=");                   //Add ApiKey "Key"
            url.Append(_apikey);                       //Append ApiKey from input
            HttpWebRequest request = MakeRequest(url.ToString()); //prepare web request
            StreamReader responseStream = new StreamReader(request.GetResponse().GetResponseStream()); //prepare responese holder
            String response = responseStream.ReadToEnd(); //fill up response
            responseStream.Close(); //Close stream
            if (sOutType == ItemType.FullUrl)
            {
                return Regex.Match(response, "longUrl>([^>]+)<", 
                    RegexOptions.Singleline | RegexOptions.IgnoreCase).Groups[1].Value;
            }
            return XmlParseGeneral(response.ToString(), xtype); //Turn it into a string
        }

        /// <summary>
        /// Разбор ответа
        /// </summary>
        /// <param name="data">данные ответа</param>
        /// <param name="type"></param>
        /// <returns></returns>
        private static String XmlParseGeneral(String data, String type)    //XML parse Function
        {

            XmlTextReader xmlrt1 = new XmlTextReader(new StringReader(data));
            while (xmlrt1.Read())
            {
                //Trace.Write("Node Type", xmlrt1.NodeType.ToString());
                string strNodeType = xmlrt1.NodeType.ToString();
                string strName = xmlrt1.Name;

                if (strNodeType == "Element" && strName == type) //get the clicks
                {
                    xmlrt1.Read();
                    return xmlrt1.Value; //Return output
                } // end if
            } return "";// end while
        }
    }
}
